package com.dogiant.weixin.wechat.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import com.dogiant.weixin.util.WeixinMessageDigest;
import com.dogiant.weixin.wechat.bean.WeChatReqBean;
import com.dogiant.weixin.wechat.bean.WeChatRespBean;
import com.dogiant.weixin.wechat.common.Constants;
import com.dogiant.weixin.yahoo.geocode.Query;
import com.dogiant.weixin.yahoo.geocode.ResultSet;
import com.dogiant.weixin.yahoo.weather.YahooWeather;
import com.dogiant.weixin.yahoo.weather.yweather.Forecast;
import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;

@WebServlet(urlPatterns = "/WeChatServlet")
public class WeChatServlet extends HttpServlet {
	private static final long serialVersionUID = -2776902810130266533L;
	private static Logger log = Logger.getLogger(WeChatServlet.class.getName());

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String signature = req.getParameter("signature");
		String timestamp = req.getParameter("timestamp");
		String nonce = req.getParameter("nonce");
		String echostr = req.getParameter("echostr");
		// 此处需要检验signature对网址接入合法性进行校验。其实没神马用
		// 详见：<a
		// href="http://mp.weixin.qq.com/cgi-bin/readtemplate?t=wxm-callbackapi-doc&lang=zh_CN">文档</a>
		log.info(signature + " : " + timestamp + " : " + nonce + " : "
				+ echostr);
		WeixinMessageDigest wxDigest = WeixinMessageDigest.getInstance();
		boolean bValid = wxDigest.validate(signature, timestamp, nonce);
		PrintWriter out = resp.getWriter();
		if (bValid) {
			out.write(echostr);
		} else {
			out.write("validate false");
		}

	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		Scanner scanner = new Scanner(req.getInputStream());
		resp.setContentType("application/xml");
		resp.setCharacterEncoding("UTF-8");
		PrintWriter out = resp.getWriter();
		try {
			// 1、获取用户发送的信息
			StringBuffer sb = new StringBuffer(100);
			while (scanner.hasNextLine()) {
				sb.append(scanner.nextLine());
			}

			// 2、解析用户的信息
			JAXBContext jc = JAXBContext.newInstance(WeChatReqBean.class);
			Unmarshaller u = jc.createUnmarshaller();
			WeChatReqBean reqBean = (WeChatReqBean) u
					.unmarshal(new StringReader(sb.toString()));

			// 3、判定用户是否发的是地理位置的PO，并查询天气
			String content = getContent(reqBean);

			// 4、创建一个回复消息
			jc = JAXBContext.newInstance(WeChatRespBean.class);
			Marshaller m = jc.createMarshaller();
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			m.setProperty(CharacterEscapeHandler.class.getName(),
					new CharacterEscapeHandler() {
						@Override
						public void escape(char[] arg0, int arg1, int arg2,
								boolean arg3, Writer arg4) throws IOException {
							arg4.write(arg0, arg1, arg2);
						}
					});
			m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
			WeChatRespBean respBean = createRespBean(reqBean, content);
			m.marshal(respBean, out);
			out.flush();
		} catch (JAXBException e) {
			log.info(e.getMessage());
		} finally {
			if (scanner != null) {
				scanner.close();
				scanner = null;
			}
			if (out != null) {
				out.close();
				out = null;
			}
		}
	}

	/**
	 * @param reqBean
	 * @param content
	 * @return
	 */
	private WeChatRespBean createRespBean(WeChatReqBean reqBean, String content) {
		WeChatRespBean respBean = new WeChatRespBean();
		respBean.setFromUserName(reqBean.getToUserName());
		respBean.setToUserName(reqBean.getFromUserName());
		respBean.setMsgType("text");
		respBean.setCreateTime(new Date().getTime());
		respBean.setContent(content);
		return respBean;
	}

	/**
	 * @param reqBean
	 * @throws JAXBException
	 * @throws MalformedURLException
	 */
	private String getContent(WeChatReqBean reqBean) throws JAXBException,
			MalformedURLException {
		StringBuffer content = new StringBuffer("亲，");
		switch (reqBean.getMsgType()) {
		case Constants.MSGTYPE_TEXT:
			if ("hello".equals(reqBean.getContent())) {
				// 这是新用户关注时默认发的一条信息。可以做一个欢迎处理。
				content.append("这是一个demo演示。随便聊聊正在开发中。[愉快]");
			} else {
				// 如果用兴趣，可以尝试做一个小黄鸡的服务。<a
				// href="http://developer.simsimi.com/api">小黄鸡</a>
				content.append("我没工夫和你聊天，我很忙的。想跟我聊天还得一段给我点开发时间。[右哼哼]");
			}
			break;
		case Constants.MSGTYPE_LOCATION:
			// 此处先调用Yahoo的PlaceFinder服务，获取用户当前所在地的woeid。
			// 再调用Yahoo的Weather服务获取天气情况。
			// String placeUrl = "http://where.yahooapis.com/geocode?location="
			// + reqBean.getLocation_X() + "+" + reqBean.getLocation_Y() +
			// "&gflags=R";
			// 上面的版本目前已经收费，修改成以下方式的免费版
			// http://developer.yahoo.com/boss/geo/docs/free_YQL.html#table_pm
			// http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.placefinder%20where%20text=%2239.744192,116.537398%22%20and%20gflags=%22R%22
			String placeUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.placefinder%20where%20text=%22"
					+ reqBean.getLocation_X()
					+ ","
					+ reqBean.getLocation_Y()
					+ "%22%20and%20gflags=%22R%22";
			log.info(placeUrl);
			JAXBContext jc = JAXBContext.newInstance(Query.class);
			Unmarshaller u = jc.createUnmarshaller();
			URL url = new URL(placeUrl);
			Query query = (Query) u.unmarshal(url);
			content.append(query.getResults().get(0).getCity() + "：");
			String weatherUrl = String.format(
					"http://weather.yahooapis.com/forecastrss?w=%s&u=c", query
							.getResults().get(0).getWoeid());
			log.info(weatherUrl);
			url = new URL(weatherUrl);
			jc = JAXBContext.newInstance(YahooWeather.class);
			u = jc.createUnmarshaller();
			YahooWeather weather = (YahooWeather) u.unmarshal(url);
			List<Forecast> list = weather.getChannel().getItem().getForecasts();
			content.append("今天最低温度" + list.get(0).getLow() + "℃，最高温度"
					+ list.get(0).getHigh() + "℃；");
			content.append("明天最低温度" + list.get(1).getLow() + "℃，最高温度"
					+ list.get(1).getHigh() + "℃。");
			if (list.get(0).getHigh() <= 15 || list.get(1).getHigh() <= 15) {
				content.append("天凉了，注意保暖哦。该南飞的难飞，实在扛不住就冬眠吧!");
			} else if (list.get(0).getHigh() <= 25 || list.get(1).getHigh() <= 25) {
				if (list.get(0).getCode() >= 26 && list.get(0).getCode() <= 32) {
					content.append("晴空万里，出去走走吧。");
				}
			} else {
				content.append("出去看看大街上的黑丝吧。");
			}
			break;
		case Constants.MSGTYPE_IMAGE:
			content.append("好漂亮的图片。[色]");
			break;
		case Constants.MSGTYPE_LINK:
			content.append("稍等，我看看。");
			break;
		case Constants.MSGTYPE_EVENT:
			switch (reqBean.getEvent()) {
				case "subscribe":
					content.append("感谢您订阅本微信!有需要请随时联系13651277590!");
					break;
				case "unsubscribe":
					content.append("感谢您关注dodevelop，再见");
					break;
				default:
					content.append("大道之行也，天下为公。随便说点什么吧!");
					break;
			}
			break;
		default:
			content.append("大道之行也，天下为公。随便说点什么吧!");
			break;
		}
		return content.toString();
	}

	public static String getUrlContent(String path) {
		String rtn = "";
		int c;
		try {
			java.net.URL l_url = new java.net.URL(path);
			java.net.HttpURLConnection connection = (java.net.HttpURLConnection) l_url
					.openConnection();
			connection.setRequestProperty("User-agent", "Mozilla/4.0");
			connection.connect();

			// 取得输入流，并使用Reader读取
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream(), "utf-8"));// 设置编码,否则中文乱码
			System.out.println("=============================");
			System.out.println("Contents of get request");
			System.out.println("=============================");
			String lines;
			while ((lines = reader.readLine()) != null) {
				lines = new String(lines.getBytes(), "utf-8");
				System.out.println(lines);
				rtn += lines;
			}

			reader.close();
			// 断开连接
			connection.disconnect();
			System.out.println("=============================");
			System.out.println("Contents of get request ends");
			System.out.println("=============================");

			/*
			 * InputStream l_urlStream = l_connection.getInputStream(); while
			 * (((c = l_urlStream.read()) != -1)) { int all =
			 * l_urlStream.available(); byte[] b = new byte[all];
			 * l_urlStream.read(b); rtn += new String(b, "UTF-8"); } //
			 * Thread.sleep(2000); l_urlStream.close();
			 */
		} catch (Exception e) {
			e.printStackTrace();
		}

		return rtn;
	}

	public static void main(String[] args) throws JAXBException, IOException {
		StringBuffer content = new StringBuffer("亲，");
		String placeUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.placefinder%20where%20text=%2239.744192,116.537398%22%20and%20gflags=%22R%22";
		log.info(placeUrl);
		JAXBContext jc = JAXBContext.newInstance(Query.class);
		Unmarshaller u = jc.createUnmarshaller();
		
		/*String s = getUrlContent(placeUrl);
		System.out.println("content==" + s);*/
		/*
		 * HttpConnectionClient client = getHttpConnectionClient();
		 * client.setCharset("GBK"); //请求编码，默认同codeing client.setCodeing("GBK");
		 * //返回数据转换编码，默认为GBK result = client.getContextByGetMethod(uri);
		 */

		URL url = new URL(placeUrl);
		java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url
				.openConnection();
		connection.setRequestProperty("User-agent", "Mozilla/4.0");
		connection.connect();
		InputStreamReader reader=new InputStreamReader(connection.getInputStream(),"UTF-8");   //在此修改编码
		// String c = (String) url.getContent();
		// System.out.println(c);
		Query query = (Query) u.unmarshal(url);

		System.out.print(query.toString());
		content.append(query.getResults().get(0).getCity() + "：");
		System.out.println(query.getResults().size());
		System.out.println(query.getResults().toString());
		System.out.println(query.getResults().get(0).getCity());
		// http://weather.yahooapis.com/forecastrss?w=2151194&u=c
		String weatherUrl = String.format(
				"http://weather.yahooapis.com/forecastrss?w=%s&u=c", query
						.getResults().get(0).getWoeid());
		log.info(weatherUrl);
		url = new URL(weatherUrl);
		jc = JAXBContext.newInstance(YahooWeather.class);
		u = jc.createUnmarshaller();
		YahooWeather weather = (YahooWeather) u.unmarshal(url);
		List<Forecast> list = weather.getChannel().getItem().getForecasts();
		content.append("今天最低温度" + list.get(0).getLow() + "℃，最高温度"
				+ list.get(0).getHigh() + "℃；");
		content.append("明天最低温度" + list.get(1).getLow() + "℃，最高温度"
				+ list.get(1).getHigh() + "℃。");
		if (list.get(0).getHigh() <= 15 || list.get(1).getHigh() <= 15) {
			content.append("天凉了，注意保暖哦。该南飞的难飞，实在扛不住就冬眠吧!");
		} else if (list.get(0).getHigh() <= 25 || list.get(1).getHigh() <= 25) {
			if (list.get(0).getCode() >= 26 && list.get(0).getCode() <= 32) {
				content.append("晴空万里，出去走走吧。");
			}
		} else {
			content.append("出去看看大街上的黑丝吧。");
		}
		System.out.println(content.toString());
	}
}
